#pragma once
#include <functional>
#include <cstdint>
#include <sys/epoll.h>

class Poller;
class EventLoop;
class Channel
{
    using EventCallBack = std::function<void()>;

private:
    int _fd;
    EventLoop *_loop;
    uint32_t _events;              // 当前需要监控的事件
    uint32_t _revents;             // 当前连接触发的事件
    EventCallBack _read_callback;  // 可读事件回调
    EventCallBack _write_callback; // 可写事件回调
    EventCallBack _event_callback; // 任意事件回调
    EventCallBack _close_callback; // 关闭事件回调
    EventCallBack _error_callback; // 错误事件回调
public:
    Channel(EventLoop *loop, int fd) : _loop(loop), _fd(fd), _events(0), _revents(0) {}
    ~Channel() {}
    int Fd() { return _fd; }
    uint32_t Events() { return _events; }
    void SetREvevt(uint32_t events) { _revents = events; }
    void SetReadCallback(const EventCallBack &readCallback)
    {
        _read_callback = readCallback;
    }
    void SetWriteCallback(const EventCallBack &writeCallback)
    {
        _write_callback = writeCallback;
    }
    void SetEventCallback(const EventCallBack &eventCallback)
    {
        _event_callback = eventCallback;
    }
    void SetCloseCallback(const EventCallBack &closeCallback)
    {
        _close_callback = closeCallback;
    }
    void SetErrorCallback(const EventCallBack &errorCallback)
    {
        _error_callback = errorCallback;
    }

    void Update();
    void Remove();
    // 描述符是否可读
    bool IsReadable() { return (_events & EPOLLIN); }
    // 描述符是否可写
    bool IsWriteable() { return (_events & EPOLLOUT); }
    // 对描述符监控可读
    void EnableRead()
    {
        _events |= EPOLLIN;
        Update();
    }
    // 对描述符监控可写
    void EnableWrite()
    {
        _events |= EPOLLOUT;
        Update();
    }
    // 解除可读事件监控
    void DisableRead()
    {
        _events &= ~EPOLLIN;
        Update();
    }
    // 解除可写事件监控
    void DisableWrite()
    {
        _events &= ~EPOLLOUT;
        Update();
    }
    // 解除所有事件监控
    void DisableAll()
    {
        _events = 0;
        Update();
    }

    // 事件处理
    void HandleEvents()
    {
        if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
        {
            if (_read_callback)
                _read_callback();
        }

        if (_revents & EPOLLOUT)
        {
            if (_write_callback)
                _write_callback();
        }
        else if (_revents & EPOLLHUP)
        {
            if (_close_callback)
                _close_callback();
        }
        else if (_revents & EPOLLERR)
        {
            if (_error_callback)
                _error_callback();
        }
        if (_event_callback)
            _event_callback();
    }
};